/*************
 *************
 *   SETUP   *
 *************
 *************/

void setup(){

  //program LCD 
  pinMode(txPin, OUTPUT);
  mySerial.begin(9600);      // 9600 baud is chip comm speed   

  mySerial.print("?G216");   // set display geometry,  2 x 16 characters in this case
  delay(200);                // pause to allow LCD EEPROM to program

  mySerial.print("?Bf0");    // set backlight to f0 hex, maximum brightness is Bff
  delay(2000);  


  mySerial.print("?f");   
  mySerial.print("?x00?y0");              // cursor to first character of line 1
  mySerial.print(" MoogerDELAY TT");        //startup message

  byte i = 0;
  while (i < 5) {
    mySerial.print("?H6");     //turn off all RANGE LED's (auxiliary pins on display LCD)
    mySerial.print("?H4");   
    mySerial.print("?H5");
    delay(100);
    mySerial.print("?L4");     //BLINK RANGE LED's (auxiliary pins on display LCD)
    mySerial.print("?H5");   
    mySerial.print("?L6");
    delay(100);
    mySerial.print("?H4");     //BLINK RANGE LED's (auxiliary pins on display LCD)
    mySerial.print("?H5");   
    mySerial.print("?H6");
    delay(100);
    mySerial.print("?H4");     //BLINK RANGE LED's (auxiliary pins on display LCD)
    mySerial.print("?L5");   
    mySerial.print("?H6");
    delay(100);
    i = i++;
  }

  mySerial.print("?H5");     //turn off all RANGE LED's (auxiliary pins on display LCD)
  mySerial.print("?H4");   
  mySerial.print("?H6");

  delay(2000);

  Serial.begin(31250);  //midi baud rate
  //Serial.begin(9600);  //for debug

  // setup SPI communication with DAC
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device 
  SPCR = 0x50;   // set up SPI port
  SPSR = 0x01;

  //setup general I/O pins 


  pinMode(ping_out_Pin, OUTPUT); 
  pinMode (ping_listen_Pin, INPUT);  //do we need to intiallize this if an interrupt is attached?
  pinMode(start_calibration_Pin, INPUT); 
  digitalWrite(start_calibration_Pin, HIGH); //turn on pullup resistor 
  pinMode(SHORT_select_Pin, INPUT);
  digitalWrite(SHORT_select_Pin, HIGH); //turn on pullup resistor to make SHORT mode the default
  pinMode(relay_out_Pin, OUTPUT); 
  pinMode(BYPASS, INPUT);
  digitalWrite(BYPASS, HIGH); //turn on pullp resistor - bypass mode on HIGH

    //TAP TEMPO assignments
  pinMode(A_SW, INPUT);   /* slower faster and tap tempo button setup */
  digitalWrite(A_SW, HIGH);
  pinMode(B_SW, INPUT);
  digitalWrite(B_SW, HIGH);  

  pinMode(tapLED, OUTPUT);  /* tap tempo led */
  digitalWrite(tapLED, HIGH);

  attachInterrupt(1, ping, FALLING);   //signal is a negative pulse on valid input from missing pulse detector cct


  if (digitalRead(start_calibration_Pin) == HIGH) {  //LOADS the time value from previous calibrations unless CAL button heald down

    for (int x = 0; x < 2; x++) {  //restore time_array for SHORT and LONG time values
      for (int i=0; i < 17; i++){
        int addr = (i*4)+(2*x);
        time_array[i][x+1]= EEPROM_Read(addr); 
      }
      check_for_maxmin(x);       //restore min and max values **issue with "reduce time" message..... 
    }
  }
  else   {
    EEPROM_Write(0, -1);  //trash the previous saved set 
    EEPROM_Write(2, -1);  //trash the previous saved set 
    message_out(1, 17);  //release button
  }


  delay (100);
  while (digitalRead(start_calibration_Pin) == LOW) {  //hang up while button is heald down
  }

  sei();			// global interrupt enable

}   //END OF SETUP


/*************
 *************
 *    LOOP   *
 *************
 *************/

//TAP TEMP variables
int lastslowState = LOW;
int lastfastState = LOW;

unsigned long currentTimer[2] = {
  500, 500};  /* array of most recent tap counts */
unsigned long timeoutTime = 0;  /* this is when the timer will trigger next */

unsigned long indicatorTimeout; /* for our fancy "blink" tempo indicator */

long unsigned int message_reset_time = 0;  //millis delay value before return to default user messsage
boolean message_reset = false;             // flag to allow error message before retunring to default user message
boolean NO_calib_msg_Short = false;
boolean NO_calib_msg_Long = false;
boolean YES_calib_msg_Short = false;
boolean YES_calib_msg_Long = false;
boolean calib_fail = false;
boolean too_long = false;
boolean too_short = false;

//byte y = 0; //y = 0 on SHORT mode, y = 1 on LONG mode - set inside "get_delay_mode" function
byte last_mode = 0; //keep track of changes of SHORT / LONG modes


void loop(void)
{

  if (digitalRead(BYPASS) == HIGH) {
    //    mySerial.print("?H5");     //turn off all RANGE LED's (auxiliary pins on display LCD)
    //    mySerial.print("?H4");   
    //    mySerial.print("?H6");
    //    digitalWrite(tapLED, HIGH);
    //    message_out(0, 15);  //BYPASS message
    //    message_out(1,0);
    bypass();
  }

  /**********************************************************
   *              Prompt user to CALIBRATE                   *
   **********************************************************/
  //these are the default user messages for the sketch 
  //other routines will send status messages but will return to these by settting all the booleans false

  if (digitalRead(SHORT_select_Pin) == HIGH && time_array[0][1] == -1  && NO_calib_msg_Short == false) {
    message_out(0, 5);  //calibrate now for SHORT mode
    message_out(1, 20);
    LEDS_OFF();  //turn off LEDs
    last_mode = 2; //set up new interpolation if switching bwetween calibrated and uncalibrated modes
    NO_calib_msg_Short = true;
    NO_calib_msg_Long = false;
    YES_calib_msg_Long = false;
  }

  if (digitalRead(SHORT_select_Pin) == LOW && time_array[0][2] == -1 && NO_calib_msg_Long == false) {
    message_out(0, 5);  //calibrate now for LONG mode
    message_out(1, 21);
    LEDS_OFF(); //turn off LEDs
    last_mode = 2; //set up new interpolation if switching bwetween calibrated and uncalibrated modes
    NO_calib_msg_Long = true;
    NO_calib_msg_Short = false; 
    YES_calib_msg_Short = false;
  }

  if (digitalRead(SHORT_select_Pin) == HIGH && time_array[0][1] != -1) {   //SHORT calibrated
    Update_DAC(0);  //function will update control voltage if there are changes

    if (YES_calib_msg_Short == false) {
      message_out(0, 20);   //SHORT calibrated - message handler and user info display
      //  sends time values to second line
      mySerial.print("?x00"); 
      mySerial.print("?y1?l");
      mySerial.print(max_min_val[0][0]);    // cursor to first character of line 0
      mySerial.print(" - ");  
      mySerial.print(max_min_val[1][0]);  
      mySerial.print(" msec"); 

      // sets up the booleans for prompts
      YES_calib_msg_Short = true;  
      YES_calib_msg_Long = false;
      NO_calib_msg_Long = false;
    }
  }

  if (digitalRead(SHORT_select_Pin) == LOW && time_array[0][2] != -1) {   //LONG Calibrated
    Update_DAC(1);  //function will update control voltage if there are changes

    if (YES_calib_msg_Long == false) {
      message_out(0, 21);     //LONG Calibrated - message handler and user info display
      //sends time values to second line
      mySerial.print("?x00"); 
      mySerial.print("?y1?l");
      mySerial.print(max_min_val[0][1]);    // cursor to first character of line 0
      mySerial.print(" - ");  
      mySerial.print(max_min_val[1][1]);  
      mySerial.print(" msec"); 

      //sets up booleans for prompts
      YES_calib_msg_Long = true;
      YES_calib_msg_Short = false; 
      NO_calib_msg_Short = false; 
      //some other housekeeping stuff here
    }
  }

  /**********************************************************   
   *                 CALIBRATE                              *   
   **********************************************************/
  //end up populating three tables - time array with 17 samples, 
  //the max/min data point positions in the table, and the max/min values

  if (digitalRead(start_calibration_Pin) == LOW) {      //calibration routine 

    calibration = true; //send flag to "activate" ISR to measure echos
    digitalWrite(relay_out_Pin, HIGH);      //close relay and insert calibration signals
    LEDS_OFF();  //turn off LEDs when calibrating

    message_out(0, 6);     //Calibrating
    message_out(1, 0);

    //the "get_delay_mode" sets the LONG or SHORT modes for the calibration routine independant of SHORT or LONG switch 
    get_delay_mode();  //also calls calib() and check_for_feedback() as these functions test the data integrity

    digitalWrite(relay_out_Pin, LOW);      //disconnect calibration signals

    //    
    if (calib_fail == false) {   //functions follow here that are executed if there was a successful calibration
      //      output_array();  //debugging
      check_for_maxmin(y);    //find max/min data pairs only for the positive non-zero linear relationship of //voltage vs time//
      check_for_maxmin_error(y); //see if there are enough samples _ won't trash the array, just warns
      last_mode = 2; //force an interpolation to reset LED's etc
      for (int i=0; i < 17; i++) {
        int addr = (i*4)+(2*y);
        EEPROM_Write(addr, time_array[i][y+1]);
        delay (5);
      }
    }
  }

  /**********************************************************   
   *                      MIDI                      *   
   **********************************************************/
  //always execute
  if(Serial.available() > 0) {
    data = Serial.read();
    if(data == midi_start ) {
      play_flag = 1;
    }

    else if (data == midi_continue) {
      play_flag = 1;
    }
    else if(data == midi_stop) {
      play_flag = 0;
      reset_message(3, false);  //release the midi tap tempo display mode
    }
    else if((data == midi_clock) && (play_flag == 1)) {
      Sync();       //we have a valid midi clock tick, count them!
    }
  }
  /**********************************************************
   *        Use the BPM to set DAC voltage output            *    do we want to lock the DAC update to new BPM's only or have this free running?
   **********************************************************/
  //put these under the calibrated message as the if statements are the same, and make a function SET_DAC(y)

  //  if (digitalRead(SHORT_select_Pin) == LOW && time_array[0][2] != -1) {     //LONG mode selection, the array is initialized
  //    Update_DAC(1);
  //    y = 1;  // LONG mode
  //    tap_tempo ();               //put tap tempo under valid machine state as we need a valid calibration first
  //    subdivide_tap ();           //still need subdivide_tap in all cases 
  //    msec_old = m_sec;
  //    m_sec = (millis_tap_tempo * Subdivision) / 100;  //the 100 multiplier is just to get a few more sig digits
  //    if (msec_old != m_sec || last_mode != 1)   //check for change in BPM, subdivision, or SHORT / LONG switch position
  //      interpolate ();
  //    last_mode = 1; 
  //  }

  //  else if (digitalRead(SHORT_select_Pin) == HIGH && time_array[0][1] != -1) {   //SHORT mode selection, the array is initialized
  //    Update_DAC(0);
  //    y = 0;  // SHORT mode  
  //    tap_tempo ();               //put tap tempo under valid machine state as we need a valid calibration first
  //    subdivide_tap ();
  //    msec_old = m_sec;
  //    m_sec = (millis_tap_tempo * Subdivision) / 100;  //the 100 multiplier is just to get a few more sig digits
  //    if (msec_old != m_sec || last_mode != 0)   //check for change in BPM, subdivision, or SHORT / LONG switch position
  //      interpolate ();
  //    last_mode = 0;
  //  }



  /**********************************************************   
   *                  MESSAGE  Delay                        *   
   **********************************************************/

  if (millis() > message_reset_time && message_reset == true) {
    message_reset = false;
    NO_calib_msg_Short = false;  //set these in main loop after message_reset_time times out
    NO_calib_msg_Long = false;
    YES_calib_msg_Short = false;
    YES_calib_msg_Long = false;
  }




}  //END OF LOOP
























